package com.lx.util;//说明:


import com.lx.annotation.Note;
import com.lx.entity.Var;
import com.lx.entity.XmlNode;
import com.lx.util.exception.ResultServiceException;

import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 创建人:游林夕/2019/3/27 14 53
 */
public final class LX {
    public static final String UTF_8 = "UTF-8";
    public enum RequestMethod{POST,GET,PUT,DELETE}
    public final static String LOCALHOST_IP = OtherUtil.getIp();
    private LX(){}
    @Note("Map List Set Object[] size=0 或者 字符串==空串 或者 为 null")
    public static boolean isEmpty(Object obj){return OtherUtil.isEmpty(obj);}
    public static boolean isNotEmpty(Object s){return !isEmpty(s);}
    @Note("字符串是空白")
    public static boolean isEmpty(String s){return OtherUtil.isBlank(s);}
    @Note("字符串不为空白")
    public static boolean isNotEmpty(String s){return !OtherUtil.isBlank(s);}

    @Note("抛异常")
    public static <T>T exMsg(String msg){throw new ResultServiceException(msg);}
    public static <T>T exMsg(Throwable e){throw new RuntimeException(e);}
    @Note("抛特殊异常-ResultServiceException")
    public static <T>T exMsg(String msg, int errCode){throw new ResultServiceException(msg,errCode);}
    @Note("boo为true时抛异常")
    public static <T>T exMsg(boolean boo,String msg){return OtherUtil.exMsg(boo,msg);}
    @Note("boo为true抛特殊异常-ResultServiceException")
    public static <T>T exMsg(boolean boo,String msg, int errCode){return OtherUtil.exMsg(boo,msg,errCode);}
    @Note("判断对象为空时抛异常, 报错固定:值不能为空")
    public static void exObj(Object s){exObj(s,"值不能为空!");}
    @Note("判断对象为空时抛异常")
    public static void exObj(Object s,String exMsg){if(isEmpty(s)){exMsg(exMsg);}}

    @Note("获取随机UUID, i指定长度1-36位")
    public static String uuid(){return UUID.randomUUID().toString();}
    public static String uuid(int i){return uuid().substring(0, i<1||i>36 ? 36 : i);}
    @Note("获取随机UUID 不带-, i指定长度1-32位")
    public static String uuid32(){return UUID.randomUUID().toString().replace("-","");}
    public static String uuid32(int i){return uuid32().substring(0, i<1||i>32 ? 32 : i);}
    @Note("获取雪花id")
    public static long snowid(){return OtherUtil.snowid();}

    @Note("将对象转为Map")
    public static <T extends Map>T toMap(Class<T> t,Object obj) {return CollectionUtil.toMap(t,obj);}
    public static Var toMap(Object obj) {return CollectionUtil.toMap(Var.class,obj);}
    @Note("将对象转为其他对象")
    public static <T> T toObj(Class<T> t,Object obj){return CollectionUtil.toObj(t,obj);}
    @Note("将对象转为List")
    public static List toList(Object obj) { return CollectionUtil.toList(obj);}
    public static <T>List<T> toList(Class<T> t,Object obj){return CollectionUtil.toList(t, obj);}
    @Note("将对象转为json串")
    public static String toJSONString(Object obj) { return CollectionUtil.toJSONString(obj);}
    public static String toFormatJson(Object obj){return CollectionUtil.toFormatJson(obj);}

    @Note("调用Http请求, timeoutMillisecond:超时时间(毫秒), exMsgByFailure: 报错是否抛异常,charset: 字符集")
    public static String doPost(String url,String body){return LXHttp.doPost(url,body,null);}
    public static String doPost(String url,String body,Map<String,String> headers){return LXHttp.doPost(url,body,headers);}
    public static String doPost(String url,String body,Map<String,String> headers, int timeoutMillisecond, boolean exMsgByFailure,Charset charset){return LXHttp.doPost(url,body,headers,timeoutMillisecond,exMsgByFailure,charset);}
    public static String doGet(String url) {return LXHttp.doGet(url,null);}
    public static String doGet(String url,Map<String,String> headers) {return LXHttp.doGet(url,headers);}
    public static String doGet(String url,Map<String,String> headers, int timeoutMillisecond, boolean exMsgByFailure,Charset charset) {return LXHttp.doGet(url,headers,timeoutMillisecond,exMsgByFailure,charset);}
    public static String doPut(String url, String body, Map<String, String> headers, int millisecond, boolean exMsgByFailure) {return LXHttp.doPut(url, body, headers,millisecond, exMsgByFailure);}
    public static String doDelete(String url,Map<String, String> headers, int timeoutMillisecond, boolean exMsgByFailure){return LXHttp.doDelete(url, headers,timeoutMillisecond, exMsgByFailure);}
    public static InputStream doGetStream(String url, Map<String, String> headers, int timeoutMillisecond, boolean exMsgByFailure,Charset charset) {return LXHttp.doGetStream(url,headers,timeoutMillisecond,exMsgByFailure,charset);}
    public static InputStream doPostInputStream(String url, String body, Map<String, String> headers, int timeoutMillisecond,boolean exMsgByFailure){return LXHttp.doPostInputStream(url,body,headers,timeoutMillisecond, exMsgByFailure);}
    public static InputStream httpInputStream(String url, LX.RequestMethod method, InputStream body, Map<String,String> headers, int timeoutMillisecond, boolean exMsgByFailure) {return LXHttp.httpInputStream(url,method,body,headers,timeoutMillisecond,exMsgByFailure);}

    @Note("调用webservice接口 一般为C#form表单提交形式 asmxUrl:以asmx结尾拼接/方法名 例:http://ip:prot/xx.asmx/methodName  ;params:表单参数")
    public static String webservice(String asmxUrl ,Map<String,String> params){return OtherUtil.webservice(asmxUrl,params);}
    @Note("调用webservice接口 一般为java SOAP接口XML, wsdlUrl:wsdl地址, method:方法名, targetNamespace:命名空间 params:参数")
    public static String webservice(String wsdlUrl ,String method ,String targetNamespace,Map<String,String> params){return OtherUtil.webservice(wsdlUrl, method, targetNamespace , params);}

    @Note("对字符串进行base64编解码")
    public static String encode(String str){return SignUtil.base64Encode(str.getBytes(StandardCharsets.UTF_8));}
    public static String decode(String str){return new String(SignUtil.base64Decode(str),StandardCharsets.UTF_8);}
    @Note("对byte[]进行base64编解码")
    public static String base64Encode(byte[] data){return SignUtil.base64Encode(data);}
    public static byte[] base64EncodeToByteArray(byte[] data){return SignUtil.base64EncodeToByteArray(data);}
    public static byte[] base64Decode(byte[] data){return SignUtil.base64Decode(data);}
    public static byte[] base64Decode(String str){return SignUtil.base64Decode(str);}
    @Note("对字符串进行md5")
    public static String md5(String string){return SignUtil.md5(string);}
    public static String md5(String string, Charset charset){return SignUtil.md5(string,charset);}
    @Note("对byte[]进行md5")
    public static String md5(byte[] data){return SignUtil.md5(data);}
    @Note("拼接签名字符串,params:待拼接数据 排除字段为sign,拼接符为&,值不进行urlEncode, 参数为空时跳过拼接")
    public static String createLinkString(final Map<String, String> params) {return SignUtil.createLinkString(params,"sign" ,"&", false, true);}
    @Note("拼接签名字符串,params:待拼接数据, exclude:排除字段,connStr:拼接符为&, encode:值进行urlEncode, skipEmpty:参数为空时跳过拼接")
    public static String createLinkString(final Map<String, String> params,String exclude, String connStr, boolean encode, boolean skipEmpty) {return SignUtil.createLinkString(params,exclude, connStr, encode , skipEmpty);}
    @Note("RSA私钥签名,参数使用LX.createLinkString进行拼接")
    public static String rsaSign(final Map<String, String> params, String privateStr){return SignUtil.sign(params,privateStr);}
    @Note("RSA私钥签名")
    public static String rsaEncrypt(String data, String privateStr) {return SignUtil.encryptByPrivateKey(data, privateStr);}
    @Note("RSA公钥验证签名,参数使用LX.createLinkString进行拼接")
    public static boolean rsaVerify(Map<String, String> params,String sign, String publicKey){return SignUtil.checkByPublicKey(createLinkString(params), sign, publicKey);}
    public static boolean rsaVerify(String data,String sign, String publicKey){return SignUtil.checkByPublicKey(data, sign, publicKey);}
    @Note("DES 加解密  C# 与java 加密 将byte[]转16进制字符串 参考:https://blog.csdn.net/weixin_43996276/article/details/121085081")
    public static String desEncrypt(String data, String key) {return SignUtil.desEncrypt(data,key);}
    public static String desDecrypt(String data,String key) {return SignUtil.desDecrypt(data,key);}
    public static byte[] desEncrypt(byte[] data, String key, String ivParameter, String fillingAlgorithm, Charset charset) {return SignUtil.desEncrypt(data,key,ivParameter,fillingAlgorithm,charset);}
    public static byte[] desDecrypt(byte[] data, String key, String ivParameter, String fillingAlgorithm, Charset charset) {return SignUtil.desDecrypt(data,key,ivParameter,fillingAlgorithm,charset);}

    @Note("hmacSHA")
    public enum HmacSha {
        HmacSHA1,HmacSHA256,HmacSHA512;
        @Note("key 密钥  content 待签名加密的数据")
        public byte[] encode(byte[] key,byte[]...content){return SignUtil.hmacSHA(name(),key,content);}
        public String encode(String key,String content){return toHexString(SignUtil.hmacSHA(name(),key.getBytes(StandardCharsets.UTF_8),content.getBytes(StandardCharsets.UTF_8)));}
    }
    @Note("byte[]转16进制字符串")
    public static String toHexString(byte[] data) {return SignUtil.toHexString(data);}
    @Note("16进制字符串转byte[]")
    public static byte[] convertHexString(String data) {return SignUtil.convertHexString(data);}
    @Note("对字符串进行urlEncode编码")
    public static String urlEncode(String src) {return SignUtil.urlEncode(src);}
    @Note("对字符串进行urlDecode编码")
    public static String urlDecode(String src) {return SignUtil.urlDecode(src);}

    @Note("转xml")
    public static String toXml(Map<String, Object> params, String label, boolean skipEmpty) {return XmlHelper.toXml(null, params,label , skipEmpty);}
    public static String toXml(Collection params, String label, String childLabel, boolean skipEmpty) {return XmlHelper.toXml(null, params,label,childLabel,skipEmpty);}
    @Note("xml转map")
    public static Map<String , String> xmlToStringMap(String xml){return XmlHelper.xmlToStringMap(xml);}
    public static Map<String, XmlNode> xmlToMap(String xmlStr) {return XmlHelper.xmlToMap(xmlStr);}
    public static List<XmlNode> xmlToList(String xml){return XmlHelper.xmlToList(xml);}
    public static List<Map<String,String>> xmlToStringMapList(String xml){return XmlHelper.xmlToStringMapList(xml);}

    @Note("比较两个数字的大小")
    public static boolean compareTo(Object obj1 , Object obj2, MathUtil.Type c){return MathUtil.compareTo(obj1,obj2,c);}
    @Note("判断字符串是否为数字")
    public static boolean isNum(String str){return str.matches("(-?\\d+)(\\.\\d+)?");}
    @Note("计算数学算式结果")
    public static BigDecimal eval(String str){return MathUtil.eval(str);}
    @Note("获取精确的数字")
    public static BigDecimal getBigDecimal(Object obj){return LX.isNotEmpty(obj) ? new BigDecimal(obj.toString()) : BigDecimal.ZERO;}

    @Note("获取当前日期和时间(yyyy-MM-dd HH:mm:ss)")
    public static String getTime(){return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));}
    @Note("获取当前日期(当前时间 YYYY-MM-dd)")
    public static String getDay(){return LocalDate.now().toString();}
    @Note("获取当前时间指定格式的日期字符串")
    public static String getDate(String sdf){return LocalDateTime.now().format(DateTimeFormatter.ofPattern(sdf));}
    @Note("获取当前时间偏移指定时长后的时间字符串")
    public static String getDate(String sdf, long offset, ChronoUnit chronoUnit){return chronoUnit.addTo(LocalDateTime.now(),offset).format(DateTimeFormatter.ofPattern(sdf));}
    @Note("获取当前时间偏移指定时长后的时间")
    public static Date getDate(long offset, ChronoUnit chronoUnit){return Date.from(chronoUnit.addTo(LocalDateTime.now(),offset).atZone(ZoneId.systemDefault()).toInstant());}
    @Note("获取两个日期之间的间隔")
    public static long getBetween(ChronoUnit chronoUnit, Date date1, Date date2){return chronoUnit.between(LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault()),LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault()));}

    @Note("线程睡眠time毫秒")
    public static void sleep(long time){OtherUtil.sleep(time);}
    @Note("获取首字母小写")
    public static String initialLower(String str){return str == null ? null : str.substring(0,1).toLowerCase()+str.substring(1);}
    @Note("获取首字母大写")
    public static String initialUp(String str){return str == null ? null : str.substring(0,1).toUpperCase()+str.substring(1);}
    @Note("将对象转为字符串 为null时显示空字符串")
    public static String str(Object obj){return isEmpty(obj)?"":obj.toString();}
    @Note("字符串补位,左对齐")
    public static String left(String str,int i){return str.length()>=i?str.substring(0,i):(str+new String(new byte[i])).substring(0,i);};
    @Note("字符串补位,右对齐")
    public static String right(String str,int i){return str.length()>=i?str.substring(str.length()-i):(new String(new byte[i])+str).substring(str.length());};
    @Note("字符串补位,左对齐")
    public static String left(String str,int i,char c){return OtherUtil.left(str,i,c);}
    @Note("字符串补位,右对齐")
    public static String right(String str,int i,char c){return OtherUtil.right(str,i,c);}
    @Note("判断map中key对应的value值是否为空")
    public static void exMap(Map s , String keys){OtherUtil.exMap(s, keys);}
    @Note("判断实体里的字段是否为空")
    public static void exEntity(Object obj,String keys){OtherUtil.exEntity(obj, keys);}

    @Note("value值为null时取other")
    public static <R> R ifNull(R value, Supplier<R> other){return value != null ? value : other.get();}
    @Note("value值为null时取other")
    public static <R> R ifNull(R value, R other){return value != null ? value : other;}
    @Note("t不为空时执行func或者t的值 否则或者other的值")
    public static <T,R> R ifNotNull(T t, Function<T,R> func){return t != null ? func.apply(t) : null;}
    @Note("t不为空时执行func或者t的值 否则或者other的值")
    public static <T,R> R ifNotNull(T t, Function<T,R> func, Supplier<R> other){return t != null ? func.apply(t) : other.get();}
    @Note("value值为空时取other")
    public static <R> R ifEmpty(R value, Supplier<R> other){return LX.isEmpty(value) ? other.get() : value;}
    @Note("value值为空时取other")
    public static <R> R ifEmpty(R value, R other){return LX.isEmpty(value) ?other: value;}
    @Note("boo值为true时取value")
    public static <R> R ifTrue(boolean boo, R value, Supplier<R> other){return boo ? value:other.get();}
    @Note("boo值为true时取value")
    public static <R> R ifTrue(boolean boo, R value, R other){return boo ? value:other;}
    @Note("boo值为true时取value")
    public static <R> R ifTrue(boolean boo,  Supplier<R> value, Supplier<R> other){return boo ? value.get():other.get();}

    @Note("InputStream -> byte[]")
    public static byte[] inputStreamToByteArray(InputStream input){return OtherUtil.toByteArray(input);}
    @Note("inputStream转String")
    public static String inputStreamToString(InputStream inputStream){return inputStreamToString(inputStream,StandardCharsets.UTF_8);}
    @Note("inputStream转String, charset:字符集")
    public static String inputStreamToString(InputStream inputStream , Charset charset){return OtherUtil.streamToString(inputStream,charset);}
    @Note("inputStreamToOutputStream")
    public static void inputStreamToOutputStream(InputStream inputStream , OutputStream outputStream){OtherUtil.inputStreamToOutputStream(inputStream,outputStream);}
    @Note("将base64字符串写入文件")
    public static void base64ToFile(String base64Data, FileOutputStream fileOutputStream) throws IOException {fileOutputStream.write(base64Decode(base64Data));}
    @Note("将文件转为base64字符串")
    public static String fileToBase64(FileInputStream fileInputStream){return base64Encode(inputStreamToByteArray(fileInputStream));}

    @Note("获取类路径下的文件路径")
    public static String getClassPath(Class<?> cls, String path){return LXFileUtil.getClassPath(cls, path);}
    @Note("获取resource路径下的文件路径")
    public static String getResourcePath(String path){return LXFileUtil.getResourcePath(path);}
    @Note("获取resource路径下的文件输入流")
    public static InputStream getResourceFileInputstream(String path){return ClassLoader.getSystemResourceAsStream(LXFileUtil.getPath(path));}

}
